package com.liuyu2783.redislock.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.liuyu2783.redislock.annotation.CacheLock;
import com.liuyu2783.redislock.annotation.CacheParam;
import com.liuyu2783.redislock.service.CacheKeyGenerator;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Map;

/**
 * com.liuyu2783.redislock.service
 *
 * @author liuyu07
 * @date 2019-6-27
 */
@Service
public class CacheKeyGeneratorImpl implements CacheKeyGenerator {

    private static final Logger logger = LoggerFactory.getLogger(CacheKeyGeneratorImpl.class);

    @Override
    public String getLockKey(ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        logger.info("方法名：{}", method.getName());
        CacheLock lockAnnotation = method.getAnnotation(CacheLock.class);
        final Object[] args = pjp.getArgs();
        final Parameter[] parameters = method.getParameters();
        StringBuilder builder = new StringBuilder();
        //默认解析方法里面带 CacheParam 注解的属性,如果没有尝试着解析实体对象中的
        for (int i = 0; i < parameters.length; i++) {
            Object obj = args[i];
            if(obj.getClass().equals(JSONObject.class)){
                JSONObject jsonObject = (JSONObject) obj;
                for (Map.Entry entry : jsonObject.entrySet()) {
                        String value = entry.getValue().toString();
                        String key = entry.getKey().toString();
                        builder.append(lockAnnotation.delimiter()).append(key).append(lockAnnotation.delimiter()).append(value);
                }
            }else {
                final CacheParam annotation = parameters[i].getAnnotation(CacheParam.class);
                if (annotation == null) {
                    continue;
                }
                builder.append(lockAnnotation.delimiter()).append(annotation.name()).append(lockAnnotation.delimiter()).append(args[i]);
            }

        }
        if (StringUtils.isEmpty(builder.toString())) {
            final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
            for (int i = 0; i < parameterAnnotations.length; i++) {
                final Object object = args[i];
                final Field[] fields = object.getClass().getDeclaredFields();
                for (Field field : fields) {
                    final CacheParam annotation = field.getAnnotation(CacheParam.class);
                    if (annotation == null) {
                        continue;
                    }
                    field.setAccessible(true);
                    Object value = ReflectionUtils.getField(field, object);
                    logger.info("参数：{}={}",field,value);
                    builder.append(lockAnnotation.delimiter()).append(value);
                }
            }
        }
        return lockAnnotation.prefix() + builder.toString();
    }

}
